#include "server.h"
#include "ui_server.h"

server::server(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::server)
{
    ui->setupUi(this);
    //当客户端向服务器发送连接请求，会发送信号newConnection
    connect(&tcpserver,SIGNAL(newConnection()),this,SLOT(onNewConnection()));
    //定时器到时发送信号：timeout
    connect(&timer,SIGNAL(timeout()),SLOT(onTimeOut()));
}

server::~server()
{
    delete ui;
}

//响应客户端连接请求的槽函数
void server::onNewConnection()
{
    //获取和客户端通信的套接字
    QTcpSocket* tcpClient = tcpserver.nextPendingConnection();
    //保存套接字到容器
    tcpClientList.append(tcpClient);
    //当客户端向服务器发送消息时，这时候通信套接字发送信号：readyRead
    connect(tcpClient,SIGNAL(readyRead()),this,SLOT(onReadyRrad()));
}

//接收客户端消息的槽函数
void server::onReadyRrad()
{
    //遍历容器哪个客户端给服务器发送消息
    for(int i=0;i<tcpClientList.size();i++)
    {
        //bytesAvailable():获取当前套接字代读取的消息字节数
        //返回0代表没有
        //大于0代表有消息
        if(tcpClientList.at(i)->bytesAvailable())
        {
            //读取消息并保存
            QByteArray buf = tcpClientList.at(i)->readAll();
/*---------测试用，可删除-----------*/
//            //显示消息
//            ui->listWidget->addItem(buf);
//            //消息回滚到最底部
//            ui->listWidget->scrollToBottom();
            //转发消息给所有在线客户端
            qDebug()<<buf;
            sendMessage(buf);
        }
    }
}

//把收到的消息转发给其他客户端
void server::sendMessage(const QByteArray& buf)
{
    for (int i=0;i<tcpClientList.size();i++) {
     tcpClientList.at(i)->write(buf);
    }
}

//创建服务器按钮对应的槽函数
void server::on_pushButton_clicked()
{
    //获取服务器端口
    port = ui->lineEdit->text().toShort();
    //设置服务器IP和端口
    if(tcpserver.listen(QHostAddress::Any,port)==true)
    {
        qDebug()<<"创建服务器成功";
        //创建成功后，禁用创建服务器按钮和端口号标签
        ui->pushButton->setEnabled(false);
        ui->lineEdit->setEnabled(false);
        //开启定时器
        timer.start(3000);
    }
    else
    {
        qDebug()<<"创建服务器失败";
    }
}

//定时器到时后将执行的槽函数
void server::onTimeOut()
{
    //遍历检查容器中保存的客户端通信套接字是否已经断开链接，如果是则删除
    for (int i=0;i<tcpClientList.size();i++) {
        if(tcpClientList.at(i)->state()==QAbstractSocket::UnconnectedState)
        {
            tcpClientList.removeAt(i);
            i--;
        }
    }
}
